#pragma once
#ifndef OBR_VIRTUALPROGRAMMANAGER_H
#define OBR_VIRTUALPROGRAMMANAGER_H

#include "VirtualProgramEntry.h"

namespace OBR
{

/**
 * @brief stores entries to programs with multiple derived in use during rendering
 *
 */
class VirtualProgramManager
{
public:
    // get unique id by type
    std::map<std::type_index, size_t> type2uniqueid;

private:
    // all instances in desc sequence
    std::vector<std::shared_ptr<VirtualProgramEntry>> all_instances;
    // access using callables[callable id][instance id]
    std::vector<std::vector<std::shared_ptr<VirtualProgramEntry>>> virtual_program_table;

public:
    VirtualProgramManager();
    ~VirtualProgramManager();

    /**
     * @brief add a new callable entry
     *
     */
    void addInstance(std::shared_ptr<VirtualProgramEntry> instance);

    /**
     * @brief access ith added element
     *
     * @param idx
     * @return std::shared_ptr<VirtualProgramEntry>
     */
    std::shared_ptr<VirtualProgramEntry> operator[](uint idx);

    /**
     * @brief Get unique objects, one for each type
     *
     * @return std::vector<std::shared_ptr<VirtualProgramEntry>>
     */
    std::vector<std::shared_ptr<VirtualProgramEntry>> getUnique();

    /**
     * @brief run every uploadVirtualProgramPayload() of each unique type
     *
     */
    void uploadAllPayloads();

    /**
     * @brief get number of unique types
     *
     * @return uint
     */
    uint getUniqueCount();

    /**
     * @brief get number of total instances
     *
     * @return uint
     */
    int getInstanceCount();

    /**
     * @brief get number of instances of certain type
     *
     * @return uint
     */
    int getInstanceCount(std::type_index typeidx);
};
} // namespace OBR

#endif
